package com.nextive.tweetfinder.controller;

import java.io.IOException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONException;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.nextive.tweetfinder.DrawableManager;
import com.nextive.tweetfinder.R;
import com.nextive.tweetfinder.TwitterClient;
import com.nextive.tweetfinder.model.Tweet;

/**
 * Performs the tweet search and displays the result.
 *  
 * @author federicobaseggio
 */
public class ResultsActivity extends ListActivity {
	private ListView listView;
	private List<Tweet> tweetListCache;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.results);
		
		listView = (ListView)findViewById(android.R.id.list);
		listView.setEmptyView(findViewById(android.R.id.empty));

		if (getLastNonConfigurationInstance() == null)
		{
			AsyncTweetRetriever tweetRetrieverTask = new AsyncTweetRetriever();
			tweetRetrieverTask.execute(this.getIntent().getStringExtra("search"));
		}
		else
		{
			populateList((List<Tweet>)getLastNonConfigurationInstance());
		}
	}
	
	/**
	 * Retrieves the tweets that match the search terms as an asynchronous task
	 * and displays a progress dialog accordingly.
	 * 
	 * @author federicobaseggio
	 */
	private class AsyncTweetRetriever extends AsyncTask<String, Integer, List<Tweet>>
	{
		private ProgressDialog progressDialog;
		private String error;

		@Override
		protected void onPreExecute() {
			progressDialog = new ProgressDialog(ResultsActivity.this);
			progressDialog.setMessage(getText(R.string.searching));
			progressDialog.show();
		}

		@Override
		protected List<Tweet> doInBackground(String ... params) {
			String search = params[0];
			
			TwitterClient twitterClient = new TwitterClient();
			List<Tweet> tweets = null;
			
			try {
				tweets = twitterClient.search(search);
			} catch (ClientProtocolException e) {
				error = getText(R.string.tweet_retrieval_failed).toString();
				e.printStackTrace();
			} catch (IOException e) {
				error = getText(R.string.tweet_retrieval_failed_connection).toString();
				e.printStackTrace();
			} catch (JSONException e) {
				error = getText(R.string.tweet_retrieval_failed).toString();
				e.printStackTrace();
			} catch (ParseException e) {
				error = getText(R.string.tweet_retrieval_failed).toString();
				e.printStackTrace();
			}

			return tweets;
		}
		
		@Override
		protected void onPostExecute(List<Tweet> tweets) {
			progressDialog.dismiss();
			if (tweets != null) {
				tweetListCache = tweets;
				populateList(tweets);

			} else {
				Toast.makeText(ResultsActivity.this, error, Toast.LENGTH_SHORT)
						.show();
				ResultsActivity.this.finish();
			}
		}
	}
	
	/**
	 * Populates the list of tweets.
	 * 
	 * @param tweets
	 *            The tweets to populate the list with.
	 */
	private void populateList(List<Tweet> tweets) {
		listView.setAdapter(new TweetListAdapter(ResultsActivity.this
				.getApplicationContext(), tweets));
	}
	
	@Override
	public Object onRetainNonConfigurationInstance()
	{
		return tweetListCache;
	}
	
	/**
	 * List adapter to display Tweets.
	 * 
	 * @author federicobaseggio
	 */
	private static class TweetListAdapter extends BaseAdapter {
    	
		private final java.text.DateFormat DATE_FORMAT;
		private final java.text.DateFormat TIME_FORMAT;
		private DrawableManager drawableManager;
		private LayoutInflater inflater;
		private List<Tweet> tweets;
		private Map<Integer, ViewHolder> viewHolders;
		
		/**
		 * Constructor
		 * 
		 * @param context The application context.
		 * @param tweets The list of tweets to display.
		 */
		public TweetListAdapter(Context context, List<Tweet> tweets)
		{
			this.tweets = tweets;
			
			DATE_FORMAT = DateFormat.getMediumDateFormat(context);
			TIME_FORMAT = DateFormat.getTimeFormat(context);

			viewHolders = new HashMap<Integer, ViewHolder>();
			drawableManager = new DrawableManager();
			inflater = LayoutInflater.from(context);
		}
		
		public int getCount() {
			return tweets.size();
		}

		public Object getItem(int position) {
			return tweets.get(position);
		}

		public long getItemId(int position) {
			return tweets.get(position).getId();
		}

		public View getView(final int position, View convertView, ViewGroup parent) {
			final ViewHolder viewHolder;
			
			if (convertView == null)
			{
				convertView = inflater.inflate(R.layout.result_item, null);
				
				viewHolder = new ViewHolder();
				viewHolder.thumb = (ImageView) convertView
						.findViewById(R.id.tweetUserThumbImageView);
				viewHolder.userName = (TextView) convertView
						.findViewById(R.id.tweetUserTextView);
				viewHolder.tweet = (TextView) convertView
						.findViewById(R.id.tweetTextView);
				viewHolder.created = (TextView) convertView
						.findViewById(R.id.tweetCreatedTextView);
				convertView.setTag(viewHolder);
			}
			else
			{
				viewHolder = (ViewHolder) convertView.getTag();
			}
			
			viewHolders.put(position, viewHolder);
			
			final Tweet tweet = tweets.get(position);
			
			DrawableManager.DrawableFetchedHandler thumbFetchedHandler = new DrawableManager.DrawableFetchedHandler() {
				
				public void setDrawable(Drawable drawable) {
					tweet.setProfileImage(drawable);
					ViewHolder viewHolder = viewHolders.get(position);
					if (viewHolder.position == position)
					{
						viewHolder.thumb.setImageDrawable(tweet.getProfileImage());
						notifyDataSetChanged();
					}
				}
			};
			
			drawableManager.fetchDrawableAsync(tweet.getProfileImageUrl(),
					thumbFetchedHandler);
			viewHolder.tweet.setText(tweet.getText());
			viewHolder.userName.setText(tweet.getFromUser());
			viewHolder.created.setText(getFormattedDate(tweet.getCreated()));
			viewHolder.thumb.setImageDrawable(tweet.getProfileImage());
			viewHolder.position = position;
			
			return convertView;
		}
		
		/**
		 * Returns a string representation of the specified date and time
		 * according to phone settings.
		 * 
		 * @param calendar
		 *            A calendar object representing the date and time.
		 * @return The string representation of the specified date and time.
		 */
		private String getFormattedDate(Calendar calendar) {
			return DATE_FORMAT.format(calendar.getTime()) + " "
					+ TIME_FORMAT.format(calendar.getTime());
		}

    	/**
    	 * View holder for the tweet view.
    	 *  
    	 * @author federicobaseggio
    	 */
		static class ViewHolder
		{
			ImageView thumb;
			TextView userName;
			TextView tweet;
			TextView created;
			int position;
		}
	}
}
